﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YJKInspectModelFunc.ModelLayer;

namespace YJKInspectModelFunc.ControlLayer
{
	public class BaseAreaFinder<AreaClass, RoomClass, BoundaryClass, DoorClass, HostElementClass> where AreaClass : BaseAreaPacker where RoomClass : BaseRoomPacker where BoundaryClass : BaseBoundarySegmentPacker where DoorClass : BaseDoorPacker where HostElementClass : BaseHostInRoomPacker
	{
		public BaseAreaFinder(AreaChecker useChecker)
		{
			this.m_thisChecker = (AreaChecker)Delegate.Combine(this.m_thisChecker, useChecker);
		}

		public BaseAreaFinder()
		{
			this.m_thisChecker = (AreaChecker)Delegate.Combine(this.m_thisChecker, new AreaChecker(Utility.IfAreaIsFireAreWithOtherData));
		}

		public void SetFactoryBean(FactoryBean<AreaClass, RoomClass, BoundaryClass, DoorClass, HostElementClass> inputFactory)
		{
			if (inputFactory != null)
			{
				this.m_useAreaFactory = inputFactory.UseAreaFactory;
				this.m_roomFactory = inputFactory.RoomFactory;
				this.m_doorFactory = inputFactory.DoorFactory;
				this.m_boundarySemgentFactory = inputFactory.BoundarySemgentFactory;
				this.m_hostInRoomClassFactory = inputFactory.HostInRoomClassFactory;
			}
		}

		public List<AreaClass> GetAllAreaPackersInDocument(Autodesk.Revit.DB.Document useDoc, List<Level> useLevels, List<ICloseCurveAnalays> lstInputCloseCurveAnalys, List<Phase> lstUsePhase, List<BuiltInCategory> lstHostedCategory, bool ifRecCalculate = false)
		{
			List<AreaClass> list = new List<AreaClass>();
			List<RoomClass> list2 = new List<RoomClass>();
			if (!BaseRoomFinder<RoomClass, DoorClass, BoundaryClass, HostElementClass>.IfUseRoomFinder || ifRecCalculate)
			{
				list2 = BaseRoomFinder<RoomClass, DoorClass, BoundaryClass, HostElementClass>.GetRoomPacker(useDoc, useLevels, lstUsePhase, lstHostedCategory, this.m_roomFactory, this.m_doorFactory, this.m_boundarySemgentFactory, this.m_hostInRoomClassFactory);
			}
			else
			{
				foreach (KeyValuePair<int, BaseElementPacker> keyValuePair in ElementPackerManger.DicNowValues)
				{
					if (keyValuePair.Value is RoomClass && keyValuePair.Value is RoomClass)
					{
						list2.Add(keyValuePair.Value as RoomClass);
					}
				}
			}
			new List<Area>();
			List<Area> list3 = new List<Area>();
			foreach (Area area in (from k in new FilteredElementCollector(useDoc).OfClass(typeof(SpatialElement)).WhereElementIsNotElementType().ToElements()
			where k is Area
			select k).Cast<Area>().ToList<Area>())
			{
				if (this.m_thisChecker(area, useLevels))
				{
					list3.Add(area);
				}
			}
			foreach (Area area2 in list3)
			{
				if (this.m_useAreaFactory == null)
				{
					List<AreaClass> list4 = list;
					Type typeFromHandle = typeof(AreaClass);
					object[] array = new object[3];
					array[0] = area2;
					list4.Add((AreaClass)((object)Activator.CreateInstance(typeFromHandle, array)));
				}
				else
				{
					list.Add(this.m_useAreaFactory(area2, null, null));
				}
			}
			for (int i = 0; i < list.Count; i++)
			{
				BaseAreaPacker baseAreaPacker = list[i];
				foreach (RoomClass roomClass in list2)
				{
					if (baseAreaPacker.IfInThis(roomClass.ThisRoom))
					{
						baseAreaPacker.AddRoomPacker(roomClass);
						baseAreaPacker.AddDoorPacker(roomClass.LstBaseDoorPacker);
					}
				}
				foreach (ICloseCurveAnalays closeCurveAnalays in lstInputCloseCurveAnalys)
				{
					if (baseAreaPacker.IfInThis(closeCurveAnalays.GetThisElement()))
					{
						baseAreaPacker.AddCloseCurveAnalaysPacker(closeCurveAnalays);
						baseAreaPacker.AddDoorPacker(closeCurveAnalays.GetAllDoors());
					}
				}
			}
			return list;
		}

		private AreaChecker m_thisChecker;

		private AreaClassFactory<AreaClass> m_useAreaFactory;

		private RoomClassFactory<RoomClass> m_roomFactory;

		private DoorClassFactory<DoorClass> m_doorFactory;

		private BoundarySegmentFactory<BoundaryClass> m_boundarySemgentFactory;

		private HostInRoomClassFactory<HostElementClass> m_hostInRoomClassFactory;
	}
}
